/**
 * @Title Unzip.java
 * @Package com.sydtech.bms.util
 * @Description 解压类
 * @Copyright ©2015 Sunyard Technology
 * @Author ou.nan@sunyard.com
 * @Date 2015年10月20日 下午7:42:01
 * @Version V1.0
 */
package com.sunyard.utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
import org.apache.commons.compress.utils.IOUtils;
import sun.rmi.runtime.Log;

import java.io.*;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.zip.GZIPInputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

/**
 * @author Nan Ou
 * @className Unzip
 * @description 解压类
 * @copyright ©2015 Sunyard Technology
 * @email ou.nan@sunyard.com
 * @date 2015年10月23日 下午5:27:35
 */
@Slf4j
public class Unzip {
    /**
     * @fields (int)BUFFER : 缓存大小
     */
    static final int BUFFER = 2048;

    /**
     * @param fileName
     * @param filePath
     * @throws IOException
     * @title unzip
     * @description 解压
     */

    public static List<String> unzip(String fileName, String filePath) throws IOException {
        List<String> stringList = new ArrayList<>();
        log.info("开始解压文件:" + fileName);
        log.info("开始解压路径:" + filePath);
        ZipFile zipFile = new ZipFile(fileName);
        Enumeration<? extends ZipEntry> emu = zipFile.entries();
        while (emu.hasMoreElements()) {
            ZipEntry entry = (ZipEntry) emu.nextElement();
            if (entry.isDirectory()) {
                new File(filePath + entry.getName()).mkdirs();
                continue;
            }
            BufferedInputStream bis = new BufferedInputStream(zipFile.getInputStream(entry));
            File file = new File(filePath + entry.getName());
            log.info("解压出来的文件名:" + file.getName());
            stringList.add(filePath + file.getName());
            File parent = file.getParentFile();
            if (parent != null && (!parent.exists())) {
                parent.mkdirs();
            }
            FileOutputStream fos = new FileOutputStream(file);
            BufferedOutputStream bos = new BufferedOutputStream(fos, BUFFER);
            int count;
            byte[] data = new byte[BUFFER];
            while ((count = bis.read(data, 0, BUFFER)) != -1) {
                bos.write(data, 0, count);

            }
            bos.flush();
            bos.close();
            bis.close();
        }
        return stringList;
    }

    public static void main(String[] args) {
        deCompressGZipFile("D:\\test\\LB0LX0002DH000131DZ20210111.tar.gz", "D:\\test");
    }

    /**
     * Tar文件解压方法
     *
     * @param tarGzFile 要解压的压缩文件名称（绝对路径名称）
     * @param destDir   解压后文件放置的路径名（绝对路径名称）当路径不存在，会自动创建
     * @return 解压出的文件列表
     */
    public static List<File> deCompressGZipFile(String tarGzFile, String destDir) {

        List<File> fileList = new ArrayList<>();

        // 建立输出流，用于将从压缩文件中读出的文件流写入到磁盘
        TarArchiveEntry entry = null;
        TarArchiveEntry[] subEntries = null;
        File subEntryFile = null;
        try (FileInputStream fis = new FileInputStream(tarGzFile);
             GZIPInputStream gis = new GZIPInputStream(fis);
             TarArchiveInputStream taris = new TarArchiveInputStream(gis);) {
            while ((entry = taris.getNextTarEntry()) != null) {
                StringBuilder entryFileName = new StringBuilder();
                entryFileName.append(destDir).append(File.separator).append(entry.getName());
                File entryFile = new File(entryFileName.toString());
                if (entry.isDirectory()) {
                    if (!entryFile.exists()) {
                        entryFile.mkdir();
                    }
                    subEntries = entry.getDirectoryEntries();
                    for (int i = 0; i < subEntries.length; i++) {
                        try (OutputStream out = new FileOutputStream(subEntryFile)) {
                            subEntryFile = new File(entryFileName + File.separator + subEntries[i].getName());
                            IOUtils.copy(taris, out);
                            System.out.println(entryFileName + File.separator + subEntries[i].getName());
                        } catch (Exception e) {
                            log.error("deCompressing file failed:" + subEntries[i].getName() + "in" + tarGzFile);
                        }
                    }
                } else {
                    fileList.add(entryFile);
                    checkFileExists(entryFile);
                    OutputStream out = new FileOutputStream(entryFile);
                    IOUtils.copy(taris, out);
                    out.close();
                    //如果是gz文件进行递归解压
//                    if (entryFile.getName().endsWith(".gz")) {
//                        deCompressGZipFile(entryFile.getPath(), destDir);
//                    }
                }
            }
            //如果需要刪除之前解压的gz文件，在这里进行

        } catch (Exception e) {
            log.warn("decompress failed", e);
        }

        return fileList;
    }

    public static void checkFileExists(File file) {
        //判断是否是目录
        if (file.isDirectory()) {
            if (!file.exists()) {
                file.mkdir();
            }
        } else {
            //判断父目录是否存在，如果不存在，则创建
            if (file.getParentFile() != null && !file.getParentFile().exists()) {
                file.getParentFile().mkdirs();
            }
            try {
                file.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
